package com.coffee.netty.util;


import com.coffee.concurrent.*;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import lombok.Getter;

import java.util.concurrent.ExecutorService;

/**
 * Manager of processors 处理器管理类<br>
 * Maintains the relationship between command and command processor through command code.
 *
 * @author songkui
 * @since 2024/8/6
 */
public class ExecutorManager {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(ExecutorManager.class);
    private static ExecutorManager processorManager = new ExecutorManager();

    @Getter
    private CoffeeDisruptorPool executorPool;

    @Getter
    private CoffeeScheduler defaultScheduler;
    /**
     * The default executor, if no executor is set for processor, this one will be used 如果没有为处理类设置线程池,则默认此线程池
     */
    @Getter
    private ExecutorService defaultExecutor;

    @Getter
    private ExecutorService slowExecutor;

    /**
     * minPoolSize(线程池的基本大小): 32
     * maxPoolSize(线程池最大大小): 512
     * queueSize(任务队列大小): 1024
     * keepAliveTime(线程活动保持时间): 60s
     */
    private int minPoolSize = ExecutorConfigManager.default_tp_min_size();

    private int minSchedulerPoolSize = ExecutorConfigManager.default_tsp_min_size();

    private int maxPoolSize = ExecutorConfigManager.default_tp_max_size();

    private int queueSize = ExecutorConfigManager.default_tp_queue_size();

    private long keepAliveTime = ExecutorConfigManager.default_tp_keepalive_time();

    private ExecutorManager() {
        defaultExecutor = ThreadPool.buildThreadPool(minPoolSize, maxPoolSize, queueSize, keepAliveTime, "coffee-def");
        this.defaultScheduler = new CoffeeScheduler(minSchedulerPoolSize);
    }

    public static ExecutorManager getInstance() {
        if (processorManager == null) {
            synchronized (ExecutorManager.class) {
                if (processorManager == null) {
                    processorManager = new ExecutorManager();
                }
            }
        }
        return processorManager;
    }


    public ExecutorManager disruptor(int size) {
        int num = Runtime.getRuntime().availableProcessors() * size;
        num = Math.max(num, 32);
        logger.info("Initialize disruptorPool size {}", num);
        executorPool = new CoffeeDisruptorPool(num, "coffee-dis");
        executorPool.start();
        return this;
    }


    public ExecutorManager slowExecutor(int minPoolSize, int maxPoolSize, int queueSize){
        this.slowExecutor = ThreadPool.buildThreadPool(minPoolSize, maxPoolSize, queueSize, keepAliveTime, "netty-slow");
        return this;
    }

    public ExecutorManager slowExecutor(){
        this.slowExecutor = ThreadPool.buildThreadPool(minPoolSize, maxPoolSize, queueSize, keepAliveTime, "netty-slow");
        return this;
    }


    public CoffeeDisruptor getDisruptorByUserId(long userId) {
        int index = (int) (userId % executorPool.size());
        return executorPool.getByIndex(index);
    }

    public CoffeeDisruptor getDisruptor(int no) {
        return executorPool.getByBizNo(no);
    }


}